#![allow(dead_code)]

use std::sync::Arc;
use std::time;

use craftdig_core::registrar;
use craftdig_datamodel::message::*;
use craftdig_datamodel::world::environment::WorldEnv;
use craftdig_worldgen::traits::ChunkProvider;

/// Global static configuration parameters for the sim config.
pub struct SimConfig {
    /// Global registrar for the game environment.
    registrar: Arc<registrar::GameRegistrar>,

    /// Msg IDs table.
    msg_ids: BlockMsgIds,

    /// Target tick length.  For 20 ticks per second, this would be 50 millis.
    tick_dur: time::Duration,

    /// How often a log message about how long the previous tick took should take.
    tick_time_log_period: u64,

    /// Chunk provider for the simulation.
    chunk_prov: Arc<dyn ChunkProvider>,

    /// Distance around the player (or the origin) where we will automatically
    /// generate chunks.
    world_gen_radius: i32,

    /// World environment for simulation stuff.
    world_env: WorldEnv,
}

impl SimConfig {
    pub fn new(
        registrar: Arc<registrar::GameRegistrar>,
        msg_ids: BlockMsgIds,
        tick_dur: time::Duration,
        tick_time_log_period: u64,
        chunk_prov: Arc<dyn ChunkProvider>,
        world_gen_radius: i32,
        world_env: WorldEnv,
    ) -> Self {
        Self {
            registrar,
            msg_ids,
            tick_dur,
            tick_time_log_period,
            chunk_prov,
            world_gen_radius,
            world_env,
        }
    }

    pub fn registrar(&self) -> &registrar::GameRegistrar {
        &self.registrar
    }

    pub fn msg_ids(&self) -> &BlockMsgIds {
        &self.msg_ids
    }

    pub fn tick_dur(&self) -> time::Duration {
        self.tick_dur
    }

    pub fn tick_time_log_period(&self) -> u64 {
        self.tick_time_log_period
    }

    pub fn chunk_provider(&self) -> &dyn ChunkProvider {
        self.chunk_prov.as_ref()
    }

    pub fn world_gen_radius(&self) -> i32 {
        self.world_gen_radius
    }

    pub fn environ(&self) -> &WorldEnv {
        &self.world_env
    }
}

/// Table of IDs for various message types for important world interactions.
pub struct BlockMsgIds {
    pub onplace: MsgTyId,
    pub onbreak: MsgTyId,
    pub neighbor_update: MsgTyId,
}

impl BlockMsgIds {
    pub fn new(onplace: MsgTyId, onbreak: MsgTyId, neighbor_update: MsgTyId) -> Self {
        Self {
            onplace,
            onbreak,
            neighbor_update,
        }
    }
}
